package allod.camera

import actors._
import actors.Actor._
import allod.gui._
import javax.swing._
import java.awt.image.BufferedImage
import java.awt.{Image}
import edu.umd.cs.piccolox.swing.PScrollPane
import message.{Stop, Start, Play}
import som.{LatticeVisualizer, DendrogramEvent, Dendrogram}
import swing.event.ButtonClicked
import swing.{Frame, Button}
import allod.som.{UMatrixBuilder, Lattice}
import net.miginfocom.swing.MigLayout
import allod.concurrent.Response

/**
 * Created by IntelliJ IDEA.
 * User: allod
 * Date: 4 трав 2010
 * Time: 23:12:50
 */

class Viewer(owner: Frame, width: Int, height: Int)
        extends MigPanel("insets 0, wrap 1", "[fill,grow]", "[fill,grow][]") with Actor {
  this.start
  val handler = new Handler(this)
  handler.start
  val captureService = new CaptureService(handler, width, height)
  captureService.start
  captureService ! Play

  private var cameraStatus: CameraStatus = null

  private var capturedFrames: List[Image] = Nil

  private var settingsDialog: SettingsFrame = new SettingsFrame(owner.peer, true)
  private var uMatrixDialog: JDialog = null
  private var latticeDialog: JDialog = null
  private var dendrogramDialog: JDialog = null

  // first row
  private val dualVideoPanel = new MigPanel("insets 0", "[fill,grow][fill,grow]", "[fill,grow]")
  this.add(dualVideoPanel)

  private val backgroundImage: BufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
  val originalVideoPanel: ImagePanel = new ImagePanel(backgroundImage)
  dualVideoPanel.add(originalVideoPanel)

  val processedVideoPanel = new ImagePanel(backgroundImage)
  dualVideoPanel.add(processedVideoPanel)

  // second row
  import CameraStatus._
  var buttonsPanel = new MigPanel("insets 0", "[]push[]push[]push[]push[]")
  private val webcamButton = new Button()
  webcamButton.icon = loadIcon("record")
  webcamButton.tooltip = "Webcam control button"
  changeCameraStatusTo(CameraStatus.READY_TO_RECORD)
  buttonsPanel.add(webcamButton)

  var settingsButton = new Button("SOM settings")
  settingsButton.icon = loadIcon("preferences")
  settingsButton.tooltip = "SOM settings"
  buttonsPanel.add(settingsButton)

  private val uMatrixButton = new Button("UMatrix")
  uMatrixButton.enabled = false
  uMatrixButton.tooltip = "Show UMatrix"
  uMatrixButton.icon = loadIcon("UMatrix")
  buttonsPanel.add(uMatrixButton)

  private val latticeButton = new Button("Lattice")
  latticeButton.enabled = false
  latticeButton.tooltip = "Show lattice"
  latticeButton.icon = loadIcon("lattice")
  buttonsPanel.add(latticeButton)

  private val dendrogramButton = new Button("Dendrogram")
  dendrogramButton.enabled = false
  dendrogramButton.tooltip = "Show dendrogram"
  dendrogramButton.icon = loadIcon("dendrogram")
  buttonsPanel.add(dendrogramButton)
  this.add(buttonsPanel)

  settingsButton.reactions += {
    case ButtonClicked(_) =>
      settingsDialog = new SettingsFrame(owner.peer, true)
      settingsDialog.setVisible(true);
      if (settingsDialog.isApprovalDecision) {
        if (uMatrixDialog != null) uMatrixDialog.setVisible(false)
        if (latticeDialog != null) latticeDialog.setVisible(false)
        if (dendrogramDialog != null) dendrogramDialog.setVisible(false)
        capturedFrames = List[BufferedImage]()
        handler.enableProcessing = false
        changeCameraStatusTo(CameraStatus.READY_TO_RECORD)
      }
  }

  webcamButton.reactions += {
    case ButtonClicked(_) =>
      changeCameraStatusTo(cameraStatus.getNextStatus)
  }

  uMatrixButton.reactions += {
    case ButtonClicked(_) => uMatrixDialog.setVisible(true)
  }

  latticeButton.reactions += {
    case ButtonClicked(_) => latticeDialog.setVisible(true)
  }

  dendrogramButton.reactions += {
    case ButtonClicked(_) => dendrogramDialog.setVisible(true)
  }

  def act() {
    loop {
      react {
        case Response(sender, original, result) =>
          originalVideoPanel.image = original
          processedVideoPanel.image = result

          if (cameraStatus == CameraStatus.BLOCKED)
            capturedFrames += original

          if (settingsDialog != null && (!capturedFrames.isEmpty)) {

            handler.buildLabeledLattice(settingsDialog.getSettings, capturedFrames)
            val labeledLattice = handler.getLabeledLattice
            val dendrogram = handler.getDendrogram

            capturedFrames = Nil
            uMatrixDialog = createUMatrixDialog(labeledLattice)
            latticeDialog = createLatticeDialog(labeledLattice, dendrogram)
            dendrogramDialog = createDendrogramDialog(dendrogram)
            changeCameraStatusTo(PAUSED)
            
            while (!mailbox.isEmpty)
              mailbox.extractFirst(_ => true)
          }
        case status: CameraStatus => changeCameraStatusTo(status)
      }
    }
  }

  def changeCameraStatusTo(status: CameraStatus) {
    this.cameraStatus = status
    this.cameraStatus.prepareButton(webcamButton)
    cameraStatus match {
      case CameraStatus.INIT =>
        captureService ! Play
      case CameraStatus.READY_TO_RECORD =>
        captureService ! Play
      case CameraStatus.BLOCKED =>
        captureService ! Start(1)
      case CameraStatus.PLAYING =>
        captureService ! Play
      case CameraStatus.PAUSED =>
        captureService ! Stop
      case _ =>
    }
    val enabledStatus = (cameraStatus == CameraStatus.PLAYING) || (cameraStatus == CameraStatus.PAUSED)
    if (uMatrixButton != null) uMatrixButton.enabled = enabledStatus
    if (latticeButton != null) latticeButton.enabled = enabledStatus
    if (dendrogramButton != null) dendrogramButton.enabled = enabledStatus
  }


  private def createUMatrixDialog(lattice: Lattice): JDialog = new JDialog() {
    setTitle("UMatrix")
    setLayout(new MigLayout("", "[fill,grow]", "[fill,grow]"))
    val image = UMatrixBuilder.getImage(lattice)
    setContentPane(new JLabel(new ImageIcon(image)))
    pack()
    setLocationRelativeTo(null)
  }

  private def createLatticeDialog(lattice: Lattice, dendrogram: Dendrogram) = new JDialog {
    setTitle("Lattice")
    setLayout(new MigLayout("", "[fill,grow]", "[fill,grow]"))

    val latticeVisualizer: LatticeVisualizer = new LatticeVisualizer(lattice, dendrogram)
    latticeVisualizer.reactions += {
      case DendrogramEvent(clusters) =>
        handler.updateLabeledLattice
        pack()
    }

    setContentPane(latticeVisualizer.peer)
    pack()
    setLocationRelativeTo(null)
  }

  private def createDendrogramDialog(dendrogram: Dendrogram): JDialog = new JDialog() {
    setTitle("Dendrogram")
    setLayout(new MigLayout("", "[fill,grow]", "[fill,grow]"))
    setContentPane(new PScrollPane(dendrogram))
    dendrogram.getCamera.setViewOffset(50, 520)
    setSize(350, 600)
    setLocationRelativeTo(null)
  }
}